///
/// @file MoveInstruction.cpp
/// @brief Move指令，也就是DragonIR的Asssign指令
///
/// @author zenglj (zenglj@live.com)
/// @version 1.0
/// @date 2024-09-29
///
/// @copyright Copyright (c) 2024
///
/// @par 修改日志:
/// <table>
/// <tr><th>Date       <th>Version <th>Author  <th>Description
/// <tr><td>2024-09-29 <td>1.0     <td>zenglj  <td>新建
/// </table>
///

#include "VoidType.h"
#include <cassert>

#include "MoveInstruction.h"
#include "Function.h"
#include <GlobalVariable.h>
///
/// @brief 构造函数
/// @param _func 所属的函数
/// @param result 结构操作数
/// @param srcVal1 源操作数
///
MoveInstruction::MoveInstruction(Function * _func, Value * _result, Value * _srcVal1)
    : Instruction(_func, IRInstOperator::IRINST_OP_ASSIGN, VoidType::getType())
{
    // 结果操作数不能是常量
    addOperand(_result);
    addOperand(_srcVal1);
}

/// @brief 转换成字符串显示
/// @param str 转换后的字符串
void MoveInstruction::toString(std::string & str)
{
    Value *dstVal = getOperand(0), *srcVal = getOperand(1);
    str = ""; // 确保str初始为空字符串

    std::string srcName;
    Type* srcType = srcVal->getType();

    // 处理源操作数的加载
    Instruction * srcInst = dynamic_cast<Instruction *>(srcVal);
    if (srcInst && !srcInst->getIRName().empty() &&
        (srcInst->getOp() == IRInstOperator::IRINST_OP_FUNC_CALL || srcInst->hasResultValue())) {
        srcName = srcVal->getIRName();
    }
    else if (dynamic_cast<GlobalVariable *>(srcVal) != nullptr || dynamic_cast<LocalVariable *>(srcVal) != nullptr) {
        RegVariable * tempVar = func->newTempVariable(srcVal->getType());
        srcName = tempVar->getIRName();
        str += srcName + " = load " + srcVal->getType()->toString() + ", " + srcVal->getType()->toString() + "* " +
               srcVal->getIRName() + "\n\t";
    }
    else if(srcVal->getType()->isPointerType() && srcVal->getType() != dstVal->getType()){
        PointerType * ptype = static_cast<PointerType*>(srcVal->getType());
        Type* temptype = const_cast<Type*>(ptype->getPointeeType());
        RegVariable * tempVar = func->newTempVariable(temptype);
        srcName = tempVar->getIRName();
        str += srcName + " = load " + temptype->toString() + ", " + ptype->getPointeeType()->toString() + "* " +
               srcVal->getIRName() + "\n\t";
        srcType = temptype; // 更新源类型
    } else {
        srcName = srcVal->getIRName();
    }

    // 获取目标类型
    const Type* dstElemType = nullptr;
    if (dstVal->getType()->isPointerType()) {
        dstElemType = static_cast<PointerType*>(dstVal->getType())->getPointeeType();
    } else {
        dstElemType = dstVal->getType();
    }

    // 关键修正：处理类型转换，特别是 float 到 int 的转换
    if (dstElemType && srcType != dstElemType && !srcType->isPointerType()) {
        RegVariable* castTemp = func->newTempVariable(const_cast<Type*>(dstElemType));

        if (srcType->isFloatType() && dstElemType->isIntegerType()) {
            // float 到 int 的转换使用 fptosi
            str += castTemp->getIRName() + " = fptosi " + srcType->toString() + " " + srcName +
                   " to " + dstElemType->toString() + "\n\t";
        }
        else if (srcType->isIntegerType() && dstElemType->isFloatType()) {
            str += castTemp->getIRName() + " = sitofp " + srcType->toString() + " " + srcName +
                   " to " + dstElemType->toString() + "\n\t";
        }
        else if (srcType->isIntegerType() && dstElemType->isIntegerType()) {
            int srcBits = srcType->getBitWidth();
            int dstBits = dstElemType->getBitWidth();

            if (srcBits < dstBits) {
                str += castTemp->getIRName() + " = sext " + srcType->toString() + " " + srcName +
                       " to " + dstElemType->toString() + "\n\t";
            }
            else if (srcBits > dstBits) {
                str += castTemp->getIRName() + " = trunc " + srcType->toString() + " " + srcName +
                       " to " + dstElemType->toString() + "\n\t";
            } else {
                str += castTemp->getIRName() + " = bitcast " + srcType->toString() + " " + srcName +
                       " to " + dstElemType->toString() + "\n\t";
            }
        }

        srcName = castTemp->getIRName(); // 使用转换结果
        srcType = const_cast<Type*>(dstElemType);
    }

    // 生成最终的 store 指令
    str += "store " + srcType->toString() + " " + srcName + ", " + dstVal->getType()->toString() + "* " + dstVal->getIRName();
}

